#include <yaml-cpp/yaml.h>

#include "util/options.h"

using namespace kawauso;
using namespace std;

#define READ_CONFIG(config, name)       \
    if (root[name].IsMap())             \
        readConfig(config, root[name])

#define READ_CONFIG_ENTRY(entry, name, node)     \
    if (node[name].IsDefined())                  \
        entry = node[name].as<decltype(entry)>()

void readConfig(LoggerOptions &options, const YAML::Node &node) {
    READ_CONFIG_ENTRY(options.enableFileStorage, "enable-file-storage", node);
    READ_CONFIG_ENTRY(options.maxFileSize, "max-file-size", node);
}

void readConfig(NetworkOptions &options, const YAML::Node &node) {

    vector<map<string, string>> list;

    READ_CONFIG_ENTRY(list, "direct-devices", node);
    for (auto &deviceInfo : list) {
        options.directDevices.emplace_back(deviceInfo["address"]);
    }

    READ_CONFIG_ENTRY(list, "emulate-devices", node);
    for (auto &deviceInfo : list) {
        options.emulateDevices.emplace_back(deviceInfo["interface"]);
    }

    READ_CONFIG_ENTRY(options.emptyRxPollThreshold, "empty-rx-poll-threshold", node);
}

void readConfig(RuntimeOptions &options, const YAML::Node &node) {
    READ_CONFIG_ENTRY(options.coreThreadNum, "core-threads", node);
    READ_CONFIG_ENTRY(options.suspendThreshold, "suspend-threshold", node);
    READ_CONFIG_ENTRY(options.maxSuspendTime, "max-suspend-time", node);
}

GeneralOptions GeneralOptions::readFromFile(const string &filepath) {
    try {
        YAML::Node root = YAML::LoadFile(filepath);
        GeneralOptions options;

        READ_CONFIG(options.loggerOptions, "logger");
        READ_CONFIG(options.networkOptions, "network");
        READ_CONFIG(options.runtimeOptions, "runtime");

        return options;
    } catch (YAML::Exception &e) {
        throw std::runtime_error(e.msg);
    }
}
